package com.ben.utils.ui

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Rect
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur
import android.view.PixelCopy
import android.view.View
import android.view.Window
import android.view.WindowManager
import com.ben.utils.reflect.ReflectUtils
import com.ben.utils.ext.tryCatch
import kotlin.math.roundToInt

object UIUtils {
    /**
     * 图片缩放比例
     */
    private const val BITMAP_SCALE = 0.2f

    /**
     * 将传入的 View 绘制到 Bitmap 中,然后做模糊处理
     */
    fun captureView(context: Context, view: View, window: Window): Bitmap? {
        try {
            val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val location = IntArray(2)
                view.getLocationInWindow(location)
                PixelCopy.request(
                    window,
                    Rect(
                        location[0], location[1], location[0] + view.width,
                        location[1] + view.height
                    ),
                    bitmap, { }, Handler(Looper.getMainLooper())
                )
            } else {
                val canvas = Canvas(bitmap)
                view.draw(canvas)
            }
            // 将图片处理成模糊
            return blurBitmap(context, bitmap, 22f)
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        return null
    }

    fun createScreenShot(context: Context, blur: Boolean = true): Bitmap? {
        try {
            val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
            val w = context.resources.displayMetrics.widthPixels
            val h = context.resources.displayMetrics.heightPixels
            var bitmap: Bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                val crop = Rect(0, 0, w, h)
                val ro = windowManager.defaultDisplay.rotation
                ReflectUtils.reflect("android.view.SurfaceControl")
                    .method("screenshot", crop, w, h, ro).get()
            } else {
                ReflectUtils.reflect("android.view.SurfaceControl").method("screenshot", w, h)
                    .get()
            }
            bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
            return if (blur) blurBitmap(context, bitmap, 22f) else bitmap
        } catch (r: Throwable) {
            return null
        }
    }

    /**
     * 模糊图片的具体方法
     *
     * @param context 上下文对象
     * @param bitmap  需要模糊的图片
     * @param blurRadius 模糊级别 取值 0-25，值越大，越模糊
     * @return 模糊处理后的图片
     */
    public fun blurBitmap(context: Context?, _bitmap: Bitmap, blurRadius: Float): Bitmap? {
        var blurRadius = blurRadius
        if (blurRadius < 0) {
            blurRadius = 0f
        }
        if (blurRadius > 25) {
            blurRadius = 25f
        }
        var outputBitmap: Bitmap? = null
        return try {
            var bitmap: Bitmap = _bitmap

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                if (bitmap.config == Bitmap.Config.HARDWARE) {
                    bitmap = _bitmap.copy(Bitmap.Config.ARGB_8888, false)
                }
            }
            // 计算图片缩小后的长宽
            val width = (bitmap.width * BITMAP_SCALE).roundToInt()
            val height = (bitmap.height * BITMAP_SCALE).roundToInt()
            if (width < 2 || height < 2) {
                return null
            }
            // 将缩小后的图片做为预渲染的图片。
            val inputBitmap = Bitmap.createScaledBitmap(bitmap, width, height, false)
            // 创建一张渲染后的输出图片。
            outputBitmap = Bitmap.createBitmap(inputBitmap)
            // 创建RenderScript内核对象
            val rs = RenderScript.create(context)
            // 创建一个模糊效果的RenderScript的工具对象
            val blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
            // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。
            // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。
            val tmpIn = Allocation.createFromBitmap(rs, inputBitmap)
            val tmpOut = Allocation.createFromBitmap(rs, outputBitmap)
            // 设置渲染的模糊程度, 25f是最大模糊度
            blurScript.setRadius(blurRadius)
            // 设置blurScript对象的输入内存
            blurScript.setInput(tmpIn)
            // 将输出数据保存到输出内存中
            blurScript.forEach(tmpOut)
            // 将数据填充到Allocation中
            tmpOut.copyTo(outputBitmap)
            tryCatch() {
                tmpIn.destroy()
                tmpOut.destroy()
                rs.destroy()
                blurScript.destroy()
            }
            outputBitmap
        } catch (e: Exception) {
            null
        }
    }
}
